﻿using System;
using Aspects.PInvoke;

namespace Aspects.Unit
{
    public class OS
    {
        /// <summary>
        /// Get the Operating system string. Example: "Windows XP Embedded"
        /// </summary>
        /// <returns>Windows {Version} [Embedded] </returns>
        public static string getOSString()
        {
            Native.osviINFOEX osvi = new Native.osviINFOEX();
            osvi.dwosviInfoSize = osvi.GetSize();
            string theVersion = "";
            if (Native.GetVersionEx(ref osvi))
            {
                theVersion = "Windows " + osString(osvi.osMajorVersion, osvi.osMinorVersion);

                uint embeddedFlag = (uint)Enum.Parse(typeof(Suites), "Embedded");
                bool flagged = Convert.ToBoolean(embeddedFlag & osvi.suiteMask);
                if (flagged)
                {
                    theVersion += " Embedded";
                }
            }
            else
            {
                Console.WriteLine("Error getting OS version");
            }
            return theVersion;
        }

        /// <summary>
        /// Gets the major version of windows only. Xp=5, Vista = 6, W7 = 6
        /// </summary>
        /// <returns>a integer that represents the Major version of Windows currently installed</returns>
        public static int getMajorVersion()
        {
            Native.osviINFOEX osvi = new Native.osviINFOEX();
            osvi.dwosviInfoSize = osvi.GetSize();
            if (Native.GetVersionEx(ref osvi))
            {
                return osvi.osMajorVersion;
            }
            else
                return 0;
        }

        /// <summary>
        /// The product suites that are possibly installed on a system. Used in GerVersionEx.suiteMask
        /// </summary>
        [Flags]
        private enum Suites : uint
        {
            None = 0,
            Smallbusiness = 0x00000001,//
            Enterprise = 0x00000002,//Server 2008 Enterprise, Server 2003 Enterprise, Win2k Advanced Server
            Backoffice = 0x00000004,//Backoffice components
            Terminal = 0x00000010,//Terminal Services
            SmallbusinessR = 0x00000020,//Small Business Server with restrictive client license in force
            Embedded = 0x00000040,//Windows XP Embedded
            Datacenter = 0x00000080,//Server 2008 Datacenter, Server 2003 Datacenter, Win2k Datacenter server
            SingleuserTS = 0x00000100,//Remote Desktop is supported (always true unless running in application server mode)
            Personal = 0x00000200,//Vista Home Premium, Vista Home Basic, Xp Home
            Blade = 0x00000400,//Server 2003 Web edition
            StorageServer = 0x00002000,//Server 2003 Storage Server R2, Server 2003 Storage Server
            ComputeServer = 0x00004000,//Server 2003 Compute Cluster
            WH_SERVER = 0x00008000 //Windows Home Server
        }

        /// <summary>
        /// Parses the major and minor version of OS to determain the OS type
        /// </summary>
        /// <param name="major">integer representing the major version of windows</param>
        /// <param name="minor">integer representing the minor version of windows</param>
        /// <returns>A string representing which version of windows based on the Major and minor version of the OS.</returns>
        private static string osString(int major, int minor)
        {
            string operatingSystem = "";

            switch (major)
            {
                case 3:
                    operatingSystem = "NT 3.51";
                    break;
                case 4:
                    operatingSystem = "NT 4.0";
                    break;
                case 5:
                    operatingSystem = "XP";
                    break;
                case 6:
                    if (minor == 0)
                        operatingSystem = "Vista";
                    else
                        operatingSystem = "7";
                    break;
                default:
                    operatingSystem = "Unknown";
                    break;
            }

            return operatingSystem;
        }

    }
}
